package com.lagou;

import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.threadpool.ThreadPool;
import org.apache.dubbo.common.threadpool.support.fixed.FixedThreadPool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;
import java.util.concurrent.*;

public class WatchingThreadPool extends FixedThreadPool implements Runnable {

    //日志类
    private static final Logger LOGGER = LoggerFactory.getLogger(WatchingThreadPool.class);

    //报警阈值
    private static final double ALARM_PERCENT = 0.90;

    //线程池
    private static final Map<URL, ThreadPoolExecutor> EXECUTOR_MAP = new ConcurrentHashMap<>();

    @Override
    public Executor getExecutor(URL url) {
        ThreadPoolExecutor executor = (ThreadPoolExecutor) super.getExecutor(url);
        EXECUTOR_MAP.put(url, executor);
        return executor;
    }

    //类初始化时启动定时线程池 执行定时任务
    public WatchingThreadPool() {
        //3秒执行一次
        Executors.newSingleThreadScheduledExecutor()
                .scheduleWithFixedDelay(this, 1 , 3, TimeUnit.SECONDS);
    }

    @Override
    public void run() {
        for (Map.Entry<URL, ThreadPoolExecutor> entry : EXECUTOR_MAP.entrySet()) {
            URL url = entry.getKey();
            ThreadPoolExecutor executor = entry.getValue();
            //活跃线程数
            int activeCount = executor.getActiveCount();
            //总线程数
            int poolSize = executor.getCorePoolSize();
            //使用率
            double used = (double) activeCount / poolSize;
            final int usedNum = (int)(used * 100);
            LOGGER.info("线程池执行状态:[{}/{}]:{}%", activeCount, poolSize, usedNum);
            if (used > ALARM_PERCENT) {
                LOGGER.error("超出警戒值!host:{}, 当前已使用量:{}%, URL:{}", url.getIp(), usedNum, url);
            }
        }
    }
}
